import { defineStore } from 'pinia';
import { store } from '@/stores';
import { useApi } from '@/hooks/useApi';
import { commonApiWithOutComponent } from '@/utils';
import { ResultEnum } from '@/enums/httpEnum';
import type { Level } from '@/api/modules/song';
import { PlayModeEnum } from '@/enums/businessEnum';

export type PlayMode = keyof typeof PlayModeEnum;

type PlayInfo = {
  id: number;
  title: string;
  singer: string;
  durationTime: number;
  picUrl: string;
  url: string;
  level: Level;
  [key: string]: string;
};

interface PlayState {
  isPlaying: boolean;
  showPlayer: boolean;
  currentProgressTime: number;
  currentPlayIndex: number;
  playMode: PlayMode;
  playInfo: PlayInfo;
  playList: playInfo[];
}

const getRandomIndex = (playList, currentIndex) => {
  // 防止无限循环
  if (playList.length === 1) {
    return currentIndex;
  }
  let index = Math.round(Math.random() * (playList.length - 1));
  if (index === currentIndex) {
    index = getRandomIndex(playList, currentIndex);
  }
  return index;
};
const getLastSongIndex = (playMode: PlayMode, currentPlayIndex: number, playList: playInfo[]) => {
  const lastIndex = currentPlayIndex - 1;
  let result = 0;
  switch (playMode) {
    case 'sequence':
      result = lastIndex < 0 ? playList.length - 1 : lastIndex;
    case 'listLoop':
      result = (lastIndex < 0 ? playList.length - 1 : lastIndex) % playList.length;
    case 'singleLoop':
      result = lastIndex < 0 ? playList.length - 1 : lastIndex;
    case 'random':
      result = Math.round(Math.random() * (playList.length - 1));
  }
  return result;
};
const getNextSongIndex = (playMode: PlayMode, currentPlayIndex: number, playList: playInfo[]) => {
  const nextIndex = currentPlayIndex + 1;
  let result = 0;
  switch (playMode) {
    case 'sequence':
      result = nextIndex >= playList.length ? 0 : nextIndex;
      break;
    case 'listLoop':
      result = (nextIndex >= playList.length ? 0 : nextIndex) % playList.length;
      break;
    case 'singleLoop':
      result = nextIndex >= playList.length ? 0 : nextIndex;
      break;
    case 'random':
      result = Math.round(Math.random() * (playList.length - 1));
      break;
  }
  return result;
};

const { song: songApi } = useApi();
const { to: $to, message: $message } = commonApiWithOutComponent();

export const usePlayStore = defineStore({
  id: 'app-play',
  state: (): PlayState => ({
    isPlaying: false,
    showPlayer: false,
    currentProgressTime: 0,
    currentPlayIndex: -1,
    playMode: 'random',
    playInfo: {
      id: 0,
      title: '',
      singer: '',
      picUrl: '',
      url: '',
      level: 'standard',
      durationTime: 0,
    },
    playList: [],
  }),
  getters: {
    getRandomPlayIndex() {
      return getRandomIndex(this.playList, this.currentPlayIndex);
    },
  },
  actions: {
    setLastSong() {
      const lastIndex = getLastSongIndex(this.playMode, this.currentPlayIndex, this.playList);
      this.isPlaying = true;
      this.currentPlayIndex = lastIndex;
      this.currentProgressTime = 0;
      Object.assign(this.playInfo, { ...this.playList[this.currentPlayIndex] });
      this.setSongUrl();
    },
    setNextSong() {
      const nextIndex = getNextSongIndex(this.playMode, this.currentPlayIndex, this.playList);
      this.isPlaying = true;
      this.currentPlayIndex = nextIndex;
      this.currentProgressTime = 0;
      Object.assign(this.playInfo, { ...this.playList[this.currentPlayIndex] });
      this.setSongUrl();
    },
    async setSongUrl() {
      const { id, level } = this.playInfo;
      const [error, resp]: [any, any] = await $to(songApi.getSongUrl(id, level));
      if (error || resp.code !== ResultEnum.SUCCESS) {
        $message.error(resp?.msg || error?.msg || error || '');
      }
      if (resp && resp.code === ResultEnum.SUCCESS) {
        const { url } = resp.data[0];
        Object.assign(this.playInfo, { url });
      }
    },
  },
  persist: {
    key: 'PINIA-APP-PLAY-STORE',
  },
});

export const usePlayStoreOut = () => usePlayStore(store);
